package com.yunyi.user.redisSevice.impl;

import com.google.common.collect.Maps;
import com.yunyi.user.config.RedissonUtil;
import com.yunyi.user.constant.Constant;
import com.yunyi.user.redisSevice.RedisService;
import com.yunyi.user.util.RedisUtil;
import com.yunyi.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName RedisServiceImpl
 * @Description
 * @Author leizhang
 * Date 2021/8/20 11:49 下午
 * @Version 1.0
 **/
@Service
public class RedisServiceImpl implements RedisService {
    private static Logger LOGGER = LoggerFactory.getLogger(RedisServiceImpl.class);
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RedissonUtil redissonUtil;

    /**
     * @param requestParam
     * @return void
     * @Description : 设置报名人数
     * @Author : leizhang
     * @Date 11:51 下午 2021/8/20
     **/
    @Override
    public void setWorkerNumber(Map<String, Object> requestParam) throws Exception {
        //1.参数校验
        if (null == requestParam || requestParam.isEmpty()) {
            throw new Exception("参数不合法");
        }
        redisUtil.hmset(Constant.WORKER_NUMBER, requestParam, DateUtil.getOverTime_24());
    }

    /**
     * @param requestParam
     * @return void
     * @Description : 设置员工参工次数
     * @Author : leizhang
     * @Date 12:06 上午 2021/8/21
     **/
    @Override
    public void setWorkerTime(Map<String, Object> requestParam) throws Exception {
        //1.参数校验
        if (null == requestParam || requestParam.isEmpty()) {
            throw new Exception("参数不合法");
        }
        String appId = requestParam.get(Constant.APP_ID).toString();
        int number = 0;
        if (null != redisUtil.hget(Constant.WORKER_TIME, appId)) {
            number = (int) redisUtil.hget(Constant.WORKER_TIME, appId);
        }
        redisUtil.hset(Constant.WORKER_TIME, appId, number + 1);
    }

    /**
     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     * @Description : 获取剩余报名名额
     * @Author : leizhang
     * @Date 12:36 上午 2021/8/21
     **/
    @Override
    public Map<Object, Object> getWorkerNumber() throws Exception {
        Map<Object, Object> hmget = redisUtil.hmget(Constant.WORKER_NUMBER);
        return hmget;
    }

    /**
     * @param timeShiftType
     * @return void
     * @Description : 更新剩余班次名额
     * @Author : leizhang
     * @Date 1:11 上午 2021/8/21
     **/
    @Override
    public int updateWorkerNumber(String timeShiftType, String appId) {
        try {
            LOGGER.info("============={} 线程访问开始============", Thread.currentThread().getName());
            boolean lock = redissonUtil.tryLock(Constant.WORKER_NUMBER_LOCK_KEY, TimeUnit.SECONDS, 7L, 3L);
            if (lock) {
                int resultNumber = (int) redisUtil.hget(Constant.WORKER_NUMBER, timeShiftType);
                if (resultNumber <= 0) {
                    //名额已经没有了 添加等候队列
                    redisUtil.lSet(timeShiftType, appId, DateUtil.getOverTime_24());
                    return Constant.NUMBER_3;
                }
                redisUtil.hset(Constant.WORKER_NUMBER, timeShiftType, resultNumber - 1, DateUtil.getOverTime_24());
                LOGGER.info("=============================" + Thread.currentThread().getName());
                return Constant.NUMBER_1;
            }
        } catch (Exception e) {
            LOGGER.info("错误信息：{}", e.toString());
            LOGGER.info("线程：{} 获取锁失败", Thread.currentThread().getName());
        } finally {
            redissonUtil.unlock(Constant.WORKER_NUMBER_LOCK_KEY);
        }
        return Constant.NUMBER_0;
    }

    public Map<String, Object> updateWorkerNumber2(String timeShiftType, String appId, String oriType) {
        Map<String, Object> resultMap = Maps.newHashMap();
        try {
            LOGGER.info("============={} 线程访问开始============", Thread.currentThread().getName());
            boolean lock = redissonUtil.tryLock(Constant.WORKER_NUMBER_LOCK_KEY, TimeUnit.SECONDS, 7L, 3L);
            if (lock) {

                if (StringUtils.isNotBlank(oriType) && !oriType.equals(timeShiftType)) {
                    int oriTypeNumber = (int) redisUtil.hget(Constant.WORKER_NUMBER, oriType);
                    if (oriTypeNumber <= 0) {
                        //名额已经没有了
                        Object o = redisUtil.leftProp(oriType);
                        if (o == null) {
                            redisUtil.hset(Constant.WORKER_NUMBER, oriType, oriTypeNumber + 1, DateUtil.getOverTime_24());
                        } else if (!o.toString().equals(appId)) {
                            resultMap.put(Constant.APP_ID, o);
                        }
                    } else {
                        redisUtil.hset(Constant.WORKER_NUMBER, oriType, oriTypeNumber + 1, DateUtil.getOverTime_24());
                    }
                }
                //判断是否重复排队
                int resultNumber = (int) redisUtil.hget(Constant.WORKER_NUMBER, timeShiftType);
                if (resultNumber <= 0) {
                    //名额已经没有了 添加等候队列
                    List<Object> waitQueue = redisUtil.lGet(timeShiftType, 0, -1);
                    if (waitQueue.indexOf(appId) > 0) {
                        resultMap.put(Constant.STATUS, Constant.NUMBER_0);
                        return resultMap;
                    }
                    redisUtil.lSet(timeShiftType, appId,DateUtil.getOverTime_24());
                    resultMap.put(Constant.STATUS, Constant.NUMBER_3);
                    return resultMap;
                }
                redisUtil.hset(Constant.WORKER_NUMBER, timeShiftType, resultNumber - 1, DateUtil.getOverTime_24());
                LOGGER.info("=============================" + Thread.currentThread().getName());
                resultMap.put(Constant.STATUS, Constant.NUMBER_1);
                return resultMap;
            }
        } catch (Exception e) {
            LOGGER.info("错误信息：{}", e.toString());
            LOGGER.info("线程：{} 获取锁失败", Thread.currentThread().getName());
        } finally {
            redissonUtil.unlock(Constant.WORKER_NUMBER_LOCK_KEY);
        }
        resultMap.put(Constant.STATUS, Constant.NUMBER_0);
        return resultMap;
    }

    /**
     * @param appId
     * @return void
     * @Description : 候选人员排队
     * @Author : leizhang
     * @Date 12:36 下午 2021/8/21
     **/
    @Override
    public void setQueuing(String type, String appId) throws Exception {
        if (StringUtils.isBlank(appId) || StringUtils.isBlank(type)) {
            throw new Exception("候选人员排队请求参数appId为空");
        }
        redisUtil.lSet(type, appId,DateUtil.getOverTime_24());
    }

    /**
     * @param
     * @return void
     * @Description : 候选人员离开候选队列（手动取消）
     * @Author : leizhang
     * @Date 12:41 下午 2021/8/21
     **/
    @Override
    public void leaveQueue(String type, String appId) throws Exception {
        if (StringUtils.isBlank(appId) || StringUtils.isBlank(type)) {
            throw new Exception("候选人员离开候选队列请求参数appid为空");
        }
        redisUtil.lRemove(type, appId);
    }

    /**
     * @param
     * @return void
     * @Description : 人员正常离队
     * @Author : leizhang
     * @Date 12:51 下午 2021/8/21
     **/
    @Override
    public void leaveQueueProp(String type) throws Exception {
        redisUtil.leftProp(type);
    }

    /**
     * @param appId
     * @return int
     * @Description : 候选人员排队位置
     * @Author : leizhang
     * @Date 12:54 下午 2021/8/21
     **/
    @Override
    public int positionBeforeNum(String type, String appId) throws Exception {
        if (StringUtils.isBlank(appId) || StringUtils.isBlank(type)) {
            throw new Exception("候选人员位置信息请求参数appId错误");
        }
        List<Object> waitQueue = redisUtil.lGet(type, 0, -1);
        if (null == waitQueue) {
            return 0;
        }
        int i = waitQueue.indexOf(appId);
        return i;
    }

    /**
     * @param type
     * @return void
     * <p>
     * //1.已报名人员取消：
     * 1.判断当前班次类型的名额是否已满，未满 则熟练加一 若满 则从候选名单取一
     * 2.如果候选名单没有 则数量加一
     * @Description : 报名人员离队
     * @Author : leizhang
     * @Date 11:15 下午 2021/8/21
     **/
    @Override
    public Object descWorkerNumber(String type, String appId) throws Exception {
        try {
            LOGGER.info("============={} 线程访问开始============", Thread.currentThread().getName());
            boolean lock = redissonUtil.tryLock(Constant.WORKER_NUMBER_LOCK_KEY, TimeUnit.SECONDS, 7L, 3L);
            if (lock) {
                int resultNumber = (int) redisUtil.hget(Constant.WORKER_NUMBER, type);
                if (resultNumber > 0) {
                    //名额还有
                    redisUtil.hset(Constant.WORKER_NUMBER, type, resultNumber + 1, DateUtil.getOverTime_24());
                } else {
                    //名额用完了
                    Object o = redisUtil.leftProp(type);
                    if (o == null) {
                        redisUtil.hset(Constant.WORKER_NUMBER, type, resultNumber + 1, DateUtil.getOverTime_24());
                    } else if (!appId.equals(o.toString())) {
                        return o;
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.info("错误信息：{}", e.toString());
            LOGGER.info("线程：{} 获取锁失败", Thread.currentThread().getName());
        } finally {
            redissonUtil.unlock(Constant.WORKER_NUMBER_LOCK_KEY);
        }
        return null;
    }

    /**
     * @param appId
     * @param date
     * @param orderCode
     * @return void
     * @Description : 保存员工签退信息
     * @Author : leizhang
     * @Date 10:19 下午 2021/8/25
     **/
    public void saveAppQtInfo(String appId, String date, String orderCode) {
        redisUtil.hset(appId,date,orderCode);
    }

    @Override
    public void removeQtInfo(String appId, String dateSum) {
        redisUtil.hdel(appId,dateSum);
    }

    @Override
    public Object getQtInfo(String appId, String dayTime) {
        return redisUtil.hget(appId,dayTime);
    }
}
